package com.aia.prm.web.ria.app.ui.file;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.ProgressIndicator;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.FailedEvent;
import com.vaadin.ui.Upload.FinishedEvent;
import com.vaadin.ui.Upload.Receiver;
import com.vaadin.ui.Upload.StartedEvent;
import com.vaadin.ui.Upload.SucceededEvent;
import com.vaadin.ui.VerticalLayout;

/**
 * http://demo.vaadin.com/sampler#ImmediateUpload
 */
@SuppressWarnings("serial")
public class ImmediateUploadExample extends VerticalLayout {
	private static final Logger logger = Logger.getLogger(ImmediateUploadExample.class);

	private Label status = new Label("Please select a file to upload");

	private ProgressIndicator pi = new ProgressIndicator();

	private MyReceiver receiver = new MyReceiver();

	private HorizontalLayout progressLayout = new HorizontalLayout();

	private Upload upload = new Upload(null, receiver);

	public ImmediateUploadExample() {
		setSpacing(true);

		// Slow down the upload
		receiver.setSlow(true);

		addComponent(status);
		addComponent(upload);
		addComponent(progressLayout);

		// Make uploading start immediately when file is selected
		upload.setImmediate(true);
		upload.setButtonCaption("Select file");

		progressLayout.setSpacing(true);
		progressLayout.setVisible(false);
		progressLayout.addComponent(pi);
		progressLayout.setComponentAlignment(pi, Alignment.MIDDLE_LEFT);

		final Button cancelProcessing = new Button("Cancel");
		cancelProcessing.addListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				upload.interruptUpload();
			}
		});
		cancelProcessing.setStyleName("small");
		progressLayout.addComponent(cancelProcessing);

		/**
		 * =========== Add needed listener for the upload component: start,
		 * progress, finish, success, fail ===========
		 */

		upload.addListener(new Upload.StartedListener() {
			public void uploadStarted(StartedEvent event) {
				logger.debug("uploadStarted,getContentLength=" + event.getContentLength());
				logger.debug("uploadStarted,getMIMEType=" + event.getMIMEType());
				long maxSize = 2048l * 1024l * 1024l;
				if (event.getContentLength() > maxSize) {
					logger.debug("event.getContentLength() > " + maxSize + ";  interruptUpload!");
					upload.interruptUpload();
				}
				// This method gets called immediatedly after upload is started
				upload.setVisible(false);
				progressLayout.setVisible(true);
				pi.setValue(0f);
				pi.setPollingInterval(500);
				status.setValue("Uploading file \"" + event.getFilename() + "\"");
			}
		});

		upload.addListener(new Upload.ProgressListener() {
			public void updateProgress(long readBytes, long contentLength) {
				// This method gets called several times during the update
				logger.debug("updateProgress:readBytes=" + readBytes + ", contentLength=" + contentLength);
				pi.setValue(new Float(readBytes / (float) contentLength));
			}

		});

		upload.addListener(new Upload.SucceededListener() {
			public void uploadSucceeded(SucceededEvent event) {
				// This method gets called when the upload finished successfully
				logger.debug("uploadSucceeded");
				ByteArrayOutputStream out = receiver.getByteArrayOutputStream();
				byte[] byteArray = out.toByteArray();
				logger.debug("byteArray.length=" + byteArray.length);
				try {
					FileUtils.writeByteArrayToFile(new File("D:/test.txt"), byteArray);
					logger.debug("OK: FileUtils.writeByteArrayToFile(new File('D:/test.txt'), byteArray);");
				} catch (IOException e) {
					e.printStackTrace();
				}
				status.setValue("Uploading file \"" + event.getFilename() + "\" succeeded");
			}
		});

		upload.addListener(new Upload.FailedListener() {
			public void uploadFailed(FailedEvent event) {
				logger.debug("uploadFailed");
				// This method gets called when the upload failed
				status.setValue("Uploading interrupted");
			}
		});

		upload.addListener(new Upload.FinishedListener() {
			public void uploadFinished(FinishedEvent event) {
				// This method gets called always when the upload finished,
				// either succeeding or failing
				logger.debug("uploadFinished");
				progressLayout.setVisible(false);
				upload.setVisible(true);
				upload.setCaption("Select another file");
			}
		});

	}

	public static class MyReceiver implements Receiver {

		private String fileName;
		private String mtype;
		private boolean sleep;
		private int total = 0;
		File file; // File to write to.

		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

		public ByteArrayOutputStream getByteArrayOutputStream() {
			return byteArrayOutputStream;
		}

		public OutputStream receiveUpload2(String filename, String mimetype) {
			fileName = filename;
			mtype = mimetype;
			return new OutputStream() {
				@Override
				public void write(int b) throws IOException {
					total++;
					if (sleep && total % 10000 == 0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			};
		}

		public OutputStream receiveUpload(String filename, String mimetype) {
			FileOutputStream fos = null; // Output stream to write to
			file = new File("D:/" + filename);
			try {
				// Open the file for writing.
				fos = new FileOutputStream(file);
			} catch (final java.io.FileNotFoundException e) {
				// Error while opening the file. Not reported here.
				e.printStackTrace();
				return null;
			}

			return fos; // Return the output stream to write to

		}

		public OutputStream receiveUpload3(String filename, String mimetype) {
			return byteArrayOutputStream;
		}

		public String getFileName() {
			return fileName;
		}

		public String getMimeType() {
			return mtype;
		}

		public void setSlow(boolean value) {
			sleep = value;
		}

	}

}